﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RAD.LightOne.Cache
{
    #region Documentation
    ///<summary>
    /// Representa o "slot" que um objeto ocupa em uma transação, é um cache transiente com a duração do ciclo de vida da transação em banco que o contém.
    ///</summary>
    #endregion
    internal sealed class MyObjectsSlot : IEnumerable<WeakReference<MyObject>>, IDisposable
    {
        #region Fields

        private Dictionary<Guid, WeakReference<MyObject>> slot;

        #endregion

        #region Properties

        public MyObject this[Guid key]
        {
            get
            {
                if (slot.ContainsKey(key) && slot[key].IsAlive)
                {
                    GC.KeepAlive(slot[key]);
                    return slot[key].Target;
                }
                else
                {
                    if (slot.ContainsKey(key))
                    {
                        slot.Remove(key);
                    }
                 
                  return null;
                }
                
            }
            set
            {
                slot[key] = new WeakReference<MyObject>(value);
            }
        }        
        
        public int Count
        {
            get
            {
                int count = 0;
                foreach (WeakReference<MyObject> weak in this.slot.Values)
                {
                    if (weak.IsAlive) count++;
                }

                return count;
            }
        }

        public bool IsReadOnly
        {
            get { return true; }
        }
        #endregion

        #region Constructors

        public MyObjectsSlot()
        {
            this.slot = new Dictionary<Guid, WeakReference<MyObject>>();
        }

        ~MyObjectsSlot()
        {
            this.slot.Clear();
            this.slot = null;
        }

        #endregion Constructors

        #region Methods

        public void Add(MyObject item)
        {
            try
            {
                this.slot.Add(item.Id, new WeakReference<MyObject>(item));
            }
            catch { }
        }

        public void Clear()
        {
            this.slot.Clear();
        }

        public bool Contains(MyObject item)
        {
            return this.ConstainsKey(item.Id);
        }

        public bool ConstainsKey(Guid key)
        {
            if (slot.ContainsKey(key) && slot[key].IsAlive)
            {
                return true;
            }
            else
            {
                if (slot.ContainsKey(key))
                {
                    slot.Remove(key);
                }
                return false;
            }
        }

        [Obsolete("Invalid in this class",true)]
        public void CopyTo(MyObject[] array, int arrayIndex)
        {
            throw new Exception("The method or operation is not implemented.");
        }


        public bool Remove(MyObject item)
        {
            return this.slot.Remove(item.Id);
        }

        public bool RemoveKey(Guid key)
        {
            return this.slot.Remove(key);
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.slot.Clear();
        }

        #endregion

        #region IEnumerable<WeakReference<MyObject>> Members

        public IEnumerator<WeakReference<MyObject>> GetEnumerator()
        {
            return this.slot.Values.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.slot.Values.GetEnumerator();
        }

        #endregion
    }
}
